﻿using System;
using System.Linq.Expressions;
using élénkPróbája.assets;

namespace élénkPróbája.validators
{
    public class LengthValidator : PropertyValidator, ILitLengthValidator
    {
        public int Min { get; private set; }
        public int Max { get; private set; }

        public Func<object, int> MinFunc { get; set; }
        public Func<object, int> MaxFunc { get; set; }

        public LengthValidator(int min, int max) : this(min, max, () => Messages.length_error)
        {
        }

        public LengthValidator(int min, int max, Expression<Func<string>> errorMessageResourceSelector) : base(errorMessageResourceSelector)
        {
            Max = max;
            Min = min;

            if (max != -1 && max < min)
            {
                throw new ArgumentOutOfRangeException("max", "Max should be larger than min.");
            }
        }

        public LengthValidator(Func<object, int> min, Func<object, int> max)
            : this(min, max, () => Messages.length_error)
        {
        }

        public LengthValidator(Func<object, int> min, Func<object, int> max, Expression<Func<string>> errorMessageResourceSelector) : base(errorMessageResourceSelector)
        {
            MaxFunc = max;
            MinFunc = min;
        }

        protected override bool IsValid(PropertyValidatorContext context)
        {
            if (context.PropertyValue == null) return true;

            if (MaxFunc != null && MinFunc != null)
            {
                Max = MaxFunc(context.Instance);
                Min = MinFunc(context.Instance);
            }

            int length = context.PropertyValue.ToString().Length;

            if (length < Min || (length > Max && Max != -1))
            {
                context.MessageFormatter
                    .AppendArgument("MinLength", Min)
                    .AppendArgument("MaxLength", Max)
                    .AppendArgument("TotalLength", length);

                return false;
            }

            return true;
        }

    }
}